/***
 * * PROJECT
 * *    ATaG
 * * VERSION
 * *    $Revision: 1.2 $
 * * DATE
 * *    $Date: 2007/06/09 07:15:52 $
 * * LOG
 * *    $Log: AtagManager.java,v $
 * *    Revision 1.2  2007/06/09 07:15:52  animesh
 * *    update after fixing all but sets and serialization.
 * *
 * *    Revision 1.23  2007/01/04 09:14:09  lmottola
 * *    Changed constructor for AtagManager.
 * *
 * *    Revision 1.22  2006/12/20 23:05:07  lmottola
 * *    Removed reference to ATaGProgram in NodeInfo.
 * *
 * *    Revision 1.21  2006/12/14 05:15:16  lmottola
 * *    Moved Estimator in atag.compiler and various cleanup.
 * *
 * *    Revision 1.20  2006/11/05 21:11:30  lmottola
 * *    Added pre-built AtagManager for traffic app.
 * *
 * *    Revision 1.19  2006/11/03 23:08:17  lmottola
 * *    Traffic application beta running.
 * *
 * *    Revision 1.18  2006/10/30 23:54:19  animesh
 * *    completed the switch/case statement for returning scopes to DataPool.
 * *
 * *    Revision 1.17  2006/10/28 11:36:48  animesh
 * *    Added a huge switch case statement with comments for handling messages.
 * *
 * *    Revision 1.16  2006/10/27 01:28:28  lmottola
 * *    Debugging support added.
 * *
 * *    Revision 1.15  2006/10/26 23:58:31  lmottola
 * *    Bug fixes: Hello World application running in SWANS.
 * *
 * *    Revision 1.14  2006/10/26 22:51:05  lmottola
 * *    Simulation code added.
 * *
 * *    Revision 1.13  2006/10/26 00:25:52  animesh
 * *    added check for "is this task assigned to me" at startup()
 * *
 * *    Revision 1.12  2006/10/26 00:23:09  lmottola
 * *    Added main() for SWANS simulator.
 * *
 * *    Revision 1.11  2006/10/25 22:33:45  animesh
 * *    constructor now takes an ATaGProgram
 * *
 * *    Revision 1.10  2006/10/25 22:07:11  animesh
 * *    Constructor now reads a file and parses it into an ATaGProgram
 * *
 * *    Revision 1.9  2006/10/25 19:36:10  animesh
 * *    Moved  a lot of functions to ATaGProgram. Basically broke off some functionality of the old ATaGManager into itself and ATaGProgram.
 * *
 * *    Revision 1.8  2006/10/24 22:36:07  animesh
 * *    Changed functions for sending out data. Used a lot of old code, but Luca will have to integrate it.
 * *
 * *    Revision 1.7  2006/10/24 09:17:37  animesh
 * *    Changed getOutputChannelDeclaration to public to let Dispatcher access it
 * *
 * *    Revision 1.6  2006/10/20 19:54:34  animesh
 * *    no message
 * *
 * *    Revision 1.5  2006/10/20 19:32:13  animesh
 * *    no message
 * *
 * *    Revision 1.4  2006/10/20 01:04:16  animesh
 * *    no message
 * *
 * *    Revision 1.3  2006/10/19 21:21:52  lmottola
 * *    Added CVS preamble.
 * *
 * *
 * *   ATaG (Abstract Task Graph) - Data-driven Macroprogramming for
 * *                                Sensor Networks
 * *
 * *   This program is free software; you can redistribute it and/or
 * *   modify it under the terms of the GNU General Public License
 * *   as published by the Free Software Foundation; either version 2
 * *   of the License, or (at your option) any later version.
 * *
 * *   This program is distributed in the hope that it will be useful,
 * *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * *   GNU General Public License for more details.
 * *
 * *   You should have received a copy of the GNU General Public License
 * *   along with this program; if not, you may find a copy at the FSF web
 * *   site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
 * *   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * *   Boston, MA  02111-1307, USA
 ***/

package atag.runtime;

//import java.util.Iterator;
import java.util.Vector;

import atag.common.ATaGProgram;
import atag.common.ATaGTaskDeclaration;
import atag.common.ScopedChannel;
import atag.runtime.ln.neighborhoodDefs.*;
//import atag.runtime.ln.swans.SimulationReferences;
import atag.runtime.platformDependent.ArchConstants;

public class AtagManager {

	protected Vector taskDecls = new Vector();

	protected DataPool m_dataPool;

	protected NodeInfo m_config;

	protected ATaGProgram m_program;

	public AtagManager() {

	}

	public void setNodeInfo(NodeInfo m_config) {
		this.m_config = m_config;
	}

	public void setDataPool(DataPool pool) {
		m_dataPool = pool;
	}

	public void setAtagProgram(ATaGProgram m_program) {
		this.m_program = m_program;
	}

	public void setUp() {

		// ************** START OF AUTO-GENERATED CODE
		// Task declarations
		// ************** END OF AUTO-GENERATED CODE
	}

        // This method is overridden in the PreBuiltAtagManager
	public Neighborhood[] getLNScopeForData(int taskID, int dataID) {

		ATaGTaskDeclaration sourceTask = (ATaGTaskDeclaration) this.m_program.getTaskList().elementAt(
				taskID);

		// ************** START OF AUTO-GENERATED CODE
		// Scope definitions
		// ************** END OF AUTO-GENERATED CODE

		return new Neighborhood[] {};
	}

        // This method is overridden in the PreBuiltAtagManager
	public Neighborhood[] getLNScopeForData(int taskID, int dataID,String partitionLabel,int partitionValue) {

		ATaGTaskDeclaration sourceTask = (ATaGTaskDeclaration) this.m_program.getTaskList().elementAt(
				taskID);

		// ************** START OF AUTO-GENERATED CODE
		// Scope definitions
		// ************** END OF AUTO-GENERATED CODE

		return new Neighborhood[] {};
	}

	// This is to be implemented by all modules
	public void start() {
		//Iterator it = taskDecls.iterator();
		m_config.debugPrint("[ATaGManager] setting up tasks");
                for(int ti=0; ti< taskDecls.size(); ti++) {
			RunnableTask t_taskDecl = (RunnableTask) taskDecls.elementAt(ti);
                        String taskName = t_taskDecl.getTaskDeclaration().getName();
                        int taskID = t_taskDecl.getTaskDeclaration().getID();
                        m_config.debugPrint("[ATaGManager] looking at the " + taskName + ", ID = "+taskID+" now");
                        if (t_taskDecl.getTaskDeclaration().getRunAtInit()
					&& m_config.isTaskAssigned(taskID)) {
				t_taskDecl.runTask();
                                m_config.debugPrint("[ATaGManager] started the " + taskName);
                        }
		}
	}

	// For SWANS/Jist simulation
//	public static void main(String[] args) {
//
//		AtagManager atagManager = SimulationReferences.getAtagManager(Integer
//				.parseInt(args[0]));
//		RunnableTask t_taskDecl;
//
//		if ((t_taskDecl = (RunnableTask) atagManager.taskDecls.get(Integer
//				.parseInt(args[1]))).getTaskDeclaration().getRunAtInit()
//				&& atagManager.m_config.isTaskAssigned(Integer
//						.parseInt(args[1]))) {
//			t_taskDecl.runTask();
//		}
//	}

	public void newInstanceProduced(int taskID, int dataID) {

		// If data is not local, do nothing locally when it is produced

		ScopedChannel t_channelDecl = this.m_program.getChannelFromTaskAndData(
				taskID, dataID);
		if (t_channelDecl == null || !t_channelDecl.isLocal())
			return;

		int[] dependentTasks = this.m_program.getOutTasksOfData(dataID);
		m_dataPool.setTotalRefs(dependentTasks, dataID);

		int[] nowRefs = new int[ArchConstants.MAXTASKS];
		Vector toBeFired = new Vector();

		for (int ctr = 0; ctr < dependentTasks.length; ctr++) {
			// If task is not dependent on this data item, go to next task
			if (dependentTasks[ctr] == 0)
				continue;
			// System.out.println("checking task " + ctr);
			// If task is dependent but is not assigned to this node, go to next
			// task
			if (!m_config.isTaskAssigned(ctr)) {
				// System.out.println("Task not assigned.");
				continue;
			}

			RunnableTask thisTask = (RunnableTask) taskDecls.elementAt(ctr);
			if (thisTask.getTaskDeclaration().getFiringRule()[0] == ATaGTaskDeclaration.FIRING_ANYDATA) {
				nowRefs[ctr] = 1;
				toBeFired.addElement(thisTask);
			} else {
				// the task is all-data, check if other data is ready
				int[] flagArray = this.m_program.getInDataOfTask(ctr);
				boolean allOtherDataReady = true;
				for (int i = 0; i < flagArray.length; i++)
					if (flagArray[i] == 1 && (i != dataID)
							&& !m_dataPool.isDataReady(taskID, i)) {
						allOtherDataReady = false;
						break;
					}
				if (allOtherDataReady) {
					System.out.println("Starting alldata task " + ctr);
					nowRefs[ctr] = 1;
					toBeFired.addElement(thisTask);
				}
			}
		}
		m_dataPool.setNowRefs(nowRefs, dataID);
		//Iterator it = toBeFired.iterator();
		for(int tbfi=0; tbfi<toBeFired.size(); tbfi++) {
			((RunnableTask) toBeFired.elementAt(tbfi)).runTask();
		}
	}

	public ATaGProgram getAtagPrg() {
		return m_program;
	}
}
